package com.mingqijia.gassafety.authority.web.facade.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gap.basic.exception.BizException;
import com.mingqijia.gassafety.authority.api.req.config.*;
import com.mingqijia.gassafety.authority.api.resp.config.DictionaryItemRespDTO;
import com.mingqijia.gassafety.authority.api.resp.config.DictionaryRespDTO;
import com.mingqijia.gassafety.authority.api.web.facade.DictionaryManageFacade;
import com.mingqijia.gassafety.authority.dal.command.*;
import com.mingqijia.gassafety.authority.dal.handler.ConfigureTranslator;
import com.mingqijia.gassafety.authority.dal.provider.ConfigureProvider;
import com.mingqijia.gassafety.authority.dal.provider.DictionaryProvider;
import com.mingqijia.gassafety.db.entity.Dictionary;
import com.mingqijia.gassafety.db.entity.OperateRecord;
import com.mingqijia.gassafety.db.entity.auth.DictionaryItemEntry;
import com.mingqijia.gassafety.db.entity.auth.ParamConfigEntry;
import com.mingqijia.gassafety.db.mapper.DictionaryMapper;
import com.mingqijia.gassafety.db.mapper.OperateRecordMapper;
import com.mingqijia.gassafety.db.mapper.auth.CompanyMapper;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.enums.ParamType;
import com.mingqijia.gassafety.shared.enums.RunningState;
import com.mingqijia.gassafety.shared.enums.YesNoEnum;
import com.mingqijia.gassafety.shared.facade.BaseFacade;
import com.mingqijia.gassafety.shared.handler.GlobalAuthenticationException;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import com.mingqijia.gassafety.shared.utils.RedisCacheExt;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.*;

import static com.mingqijia.gassafety.shared.constant.Constants.OPERATE_RESULT_SUCCESS;

/**
 * 参数配置REST接口实现
 *
 * @author Damon S.
 * @version v1.0.1
 * @date 2021年04月13日 18:42
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@Service
public class DictionaryManageFacadeImpl extends BaseFacade implements DictionaryManageFacade {

    private final DictionaryProvider dProvider;
    private final ConfigureProvider cProvider;
    private final ConfigureTranslator translator;


    @Autowired
    OperateRecordMapper operateRecordMapper;

    @Autowired
    DictionaryMapper dictionaryMapper;

    @Autowired
    CompanyMapper companyMapper;

    @Autowired
    RedisCacheExt redisUtil;

    @Override
    public Integer checkDictDuplication(String name, String code) {
        return cProvider.checkDuplication(name, code);
    }

    @Override
    public Integer checkDictItemDuplication(String dictCode, String name, String code) {
        return dProvider.checkDuplication(dictCode, name, code);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void duplicateParams2Company(String spId) {
        dProvider.duplicateDictionaries2Org(spId);
        List<String> names=dictionaryMapper.selectConfigureBySpId(spId);
        String name="";
        String detailName="";
        if (CollectionUtil.isNotEmpty(names)){
            for (String n : names) {
                name=name+"\n"+n;
                detailName=detailName+"【"+n+"】";
            }
        }
        //企业级操作日志
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setOperateType(47);
        operateRecord.setDetail("同步数据字典");
        operateRecord.setOperatorCode(ApplicationUtils.getWorkingUser().getUsername());
        operateRecord.setOperatorName(ApplicationUtils.getWorkingUser().getName());
        operateRecord.setSpId(ApplicationUtils.getWorkingSpId());
        operateRecord.setOperateResult(OPERATE_RESULT_SUCCESS);
        operateRecord.setMenu("dictionaries");
        operateRecord.setDetail("同步数据字典"+detailName );
        operateRecord.setCommonInfo(name);
        operateRecord.setCreatedAt(new Date());
        operateRecord.setUpdatedAt(new Date());
        operateRecordMapper.insert(operateRecord);
    }

    @Override
    public DictionaryRespDTO findDictByCode(String dictCode) {
        // 先查企业，再查平台
        String workingSpId = ApplicationUtils.getHeaderSpId();
        ParamConfigEntry entry = cProvider.getConfigByKey(
                dictCode, ParamType.DICTIONARY, workingSpId);
        if (ObjectUtils.isEmpty(entry)) {
            workingSpId = Constants.PLATFORM_SP;
            entry = cProvider.getConfigByKey(dictCode,
                    ParamType.DICTIONARY, workingSpId);
            // 可继承的参数不再向集团获取
            if (!ObjectUtils.isEmpty(entry) && YesNoEnum.Y.getCode() == entry.getConfigurable()) {
                log.error("该企业指定参数不存在[code={}]", dictCode);
                throw new GlobalAuthenticationException("错误：[该企业" + dictCode + "]参数不存在");
            }
        }
        if (ObjectUtils.isEmpty(entry)) {
            log.error("指定参数不存在[code={}]", dictCode);
            throw new GlobalAuthenticationException("错误：[" + dictCode + "]参数不存在");
        }
        DictionaryRespDTO dictionary = translator.toDictRespDTO(entry);
        Page<DictionaryItemEntry> results = findDictionaryItems(
                dictCode, null, 1L, Constants.LONG_1_KILO, workingSpId);

        dictionary.setChildren(translator.toItemRespDTO(results.getRecords()));
        return dictionary;
    }

    @Override
    public PageUtil<DictionaryRespDTO> findDictionary(@Valid QueryDictionaryReqDTO req) {
        QueryParamConfigCommand command = translator.toCommand(req);
        command.setType(ParamType.DICTIONARY);
        // 查询字典列表
        Page<ParamConfigEntry> results = cProvider.find(command);
        List<DictionaryRespDTO> records = cProvider.buildRespDTO(results.getRecords());
        return PageUtil.init(results, records);
    }

    @Override
    public PageUtil<DictionaryItemRespDTO> findDictionaryItem(String dictCode, String name,
                                                              Long page, Long pageSize) {
        Page<DictionaryItemEntry> results;
        try {
            results = findDictionaryItems(
                    dictCode, name,
                    page, pageSize,
                    ApplicationUtils.getWorkingSpId());
        } catch (Exception e) {
            String spId = ApplicationUtils.getWorkingSpId();
            results = findDictionaryItems(
                    dictCode, name,
                    page, pageSize,
                    Constants.PLATFORM_SP);
            if (!CollectionUtils.isEmpty(results.getRecords())){
               int count= dictionaryMapper.selectScope(spId,dictCode);
               if (count<=0) results.setRecords(new ArrayList<>());
            }
        }
        List<DictionaryItemRespDTO> records = translator.toItemRespDTO(results.getRecords());

        return PageUtil.init(results, records);
    }

    private Page<DictionaryItemEntry> findDictionaryItems(String dictCode, String name,
                                                          Long page, Long pageSize, String spId) {
        FindDictionaryItemCommand command = FindDictionaryItemCommand.builder()
                .dictState(RunningState.RUNNING).page(page).name(name)
                .dictCode(dictCode).pageSize(pageSize).spId(spId).build();
        return dProvider.find(command);
    }

    @Override
    public String createDictionary(@Valid CreateDictionaryReqDTO req) {
        if (ObjectUtils.isEmpty(req.getConfigurable())) {
            req.setConfigurable(YesNoEnum.N.getCode());
        }
        CreateParamConfigCommand command = translator.toCommand(req);
        command.setType(ParamType.DICTIONARY);
        //企业级操作日志
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setOperateType(44);
        operateRecord.setDetail("新增数据字典");
        operateRecord.setOperatorCode(ApplicationUtils.getWorkingUser().getUsername());
        operateRecord.setOperatorName(ApplicationUtils.getWorkingUser().getName());
        operateRecord.setSpId(ApplicationUtils.getWorkingSpId());
        operateRecord.setOperateResult(OPERATE_RESULT_SUCCESS);
        operateRecord.setMenu("dictionaries");
        operateRecord.setDetail("新增数据字典【"+req.getName()+"】"    );
        operateRecord.setCommonInfo(req.getName());
        operateRecord.setCreatedAt(new Date());
        operateRecord.setUpdatedAt(new Date());
        operateRecordMapper.insert(operateRecord);
        return cProvider.create(command);
    }

    @Override
    public String createDictionaryItem(@Valid CreateDictionaryItemReqDTO req) {
        log.info("createDictionaryItem-param:{}", JSONObject.toJSONString(req));
        String ret = dProvider.create(translator.toCommand(req));
        if("sync_alarm_to_sk".equals(req.getCode())){
            redisUtil.del(Constants.SYNC_ALAM_TO_SK_IMEIS_REDIS_KEY);
        }
        return ret;
    }

    @Override
    public void updateDictionary(@Valid UpdateDictionaryReqDTO req) {
        log.info("updateDictionary-req:{}",JSONObject.toJSONString(req));
       Map<String,Object> res= dictionaryMapper.selectByConfigureId(req.getId());
       log.info("updateDictionary-res:{}",JSONObject.toJSONString(res));
        //企业级操作日志
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setOperateType(45);
        operateRecord.setDetail("修改数据字典信息");
        operateRecord.setOperatorCode(ApplicationUtils.getWorkingUser().getUsername());
        operateRecord.setOperatorName(ApplicationUtils.getWorkingUser().getName());
        operateRecord.setSpId(ApplicationUtils.getWorkingSpId());
        operateRecord.setOperateResult(OPERATE_RESULT_SUCCESS);
        operateRecord.setMenu("dictionaries");
        List<String> scope = req.getScope();
        String companyName="";
        if (req.getScopeType()==2&&scope.size()>0){
            companyName= dictionaryMapper.selectCompanyNames(scope);
        }
        String ss = res.get("scope")+"";
        String[] split =new String[1];
        if (ss.contains(",")){
             split = ss.split(",");
        }else {
            split[0]=ss;
        }
       String companyName2= dictionaryMapper.selectCompanyNames(new ArrayList<>(Arrays.asList(split)));
        if (!StringUtils.isEmpty(companyName)){
            companyName=req.getScope().equals("["+res.get("scope")+"]")? "" : "企业名称：由【" + companyName2 + "】变更成【" + companyName + "】\n";
        }
        List<String> scopes=new ArrayList<>();
        scopes.add(res.get("scope")+"");
        String platform= ("["+res.get("scope")+"]").equals("[1]")?"全平台":"按企业选择";
        String platform1= req.getScopeType()==1?"全平台":"按企业选择";
        String str = req.getCode().equals(res.get("code")) ? "" : " 编码：由【" + res.get("code") + "】变更成【" + req.getCode() + "】\n";
        String strType=req.getScope().equals(scopes) ?"":"适用企业"+"由【"+platform+"】变更成【"+platform1+"】\n";
        String strTypCode = req.getDescription().equals(res.get("description")) ? "" : "描述：由【" + res.get("description") + "】变更成【" + req.getDescription() + "】\n";
        operateRecord.setDetail("修改数据字典信息【" + req.getName() + "】\n"+ str+strType+companyName+strTypCode);

        operateRecord.setCommonInfo( req.getName());
        operateRecord.setCreatedAt(new Date());
        operateRecord.setUpdatedAt(new Date());
        log.info("updateDictionary-log:{},{},{},{}",platform,platform1,strType);
        operateRecordMapper.insert(operateRecord);
        if (!cProvider.update(translator.toCommand(req))) {
            throw new GlobalAuthenticationException("更新操作失败");
        }

    }
    @Override
    public void updateDictionaryItem(@Valid UpdateDictionaryItemReqDTO req) {
        Dictionary dictionary = dictionaryMapper.selectById(req.getId());
        if (!dProvider.update(translator.toCommand(req))) {
            throw new GlobalAuthenticationException("更新操作失败");
        }

        dictionary=  dictionary==null?new Dictionary():dictionary;
        //企业级操作日志
        String typeName = operateRecordMapper.selectNameByCode(req.getDictCode());
        log.info("removeDictionaryItem-req:{},{}",JSONObject.toJSONString(req),typeName);
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setOperateType(35);
        operateRecord.setDetail("修改数据字典");
        operateRecord.setOperatorCode(ApplicationUtils.getWorkingUser().getUsername());
        operateRecord.setOperatorName(ApplicationUtils.getWorkingUser().getName());
        operateRecord.setSpId(ApplicationUtils.getWorkingSpId());
        operateRecord.setOperateResult(OPERATE_RESULT_SUCCESS);
        operateRecord.setMenu("dictionariesInfo");
        String str = dictionary.getDescription().equals(req.getDescription())? "" : "描述：由【" + dictionary.getDescription() + "】变更成【" + req.getDescription() + "】\n";
        String strType=dictionary.getAlias().equals(req.getName()) ?"":"类型名称"+"由【"+dictionary.getAlias()+"】变更成【"+req.getName()+"】\n";
        String strTypCode = dictionary.getValue().equals(req.getValue()) ? "" : "类型编码：由【" + dictionary.getValue() + "】变更成【" + req.getValue() + "】\n";
        log.info("updateDictionaryItem-str:{},strType:{},strTypCode:{}",str,strType,strTypCode);
        operateRecord.setDetail("修改数据字典【" + typeName + "】中的类型【" + req.getName() + "】信息\n"+
                strType+strTypCode
        +str);
        operateRecord.setCommonInfo(typeName);
        operateRecord.setCreatedAt(new Date());
        operateRecord.setUpdatedAt(new Date());
        operateRecordMapper.insert(operateRecord);
        if("sync_alarm_to_sk".equals(dictionary.getDictCode())){
            redisUtil.del(Constants.SYNC_ALAM_TO_SK_IMEIS_REDIS_KEY);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeDictionary(String dictId) {
        RemoveParamConfigCommand command = RemoveParamConfigCommand.builder()
                .id(dictId).updatedBy(getUserBackendId()).build();
        // 逻辑删除字典
        if (!cProvider.remove(command)) {
            throw new GlobalAuthenticationException("删除字典失败");
        }
        ParamConfigEntry entry = cProvider.getById(dictId);
        RemoveDictionaryItemCommand command2 = RemoveDictionaryItemCommand.builder()
                .dictCode(entry.getCode()).updatedBy(getUserBackendId()).build();
        // 逻辑删除字典类型
        if (!dProvider.remove(command2)) {
            throw new GlobalAuthenticationException("删除字典失败");
        }
        //企业级操作日志
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setOperateType(46);
        operateRecord.setDetail("删除数据字典");
        operateRecord.setOperatorCode(ApplicationUtils.getWorkingUser().getUsername());
        operateRecord.setOperatorName(ApplicationUtils.getWorkingUser().getName());
        operateRecord.setSpId(ApplicationUtils.getWorkingSpId());
        operateRecord.setOperateResult(OPERATE_RESULT_SUCCESS);
        operateRecord.setMenu("dictionaries");
        operateRecord.setCommonInfo(entry.getName());
        operateRecord.setDetail("删除数据字典【"+entry.getName()+"】"    );
        operateRecord.setCreatedAt(new Date());
        operateRecord.setUpdatedAt(new Date());
        operateRecordMapper.insert(operateRecord);
        if("sync_alarm_to_sk".equals(entry.getCode())){
            redisUtil.del(Constants.SYNC_ALAM_TO_SK_IMEIS_REDIS_KEY);
        }
    }

    //TODO 操作日志
    @Override
    public void removeDictionaryItem(String itemId, String code) {
        if (!StringUtils.hasText(itemId)) {
            throw new BizException("请设置参数");
        }
        List<String> itemIds = Arrays.asList(itemId.split(Constants.STR_COMMA));
        //企业级操作日志
        String typeName = operateRecordMapper.selectNameByCode(code);
        log.info("removeDictionaryItem-itemIds:{},{}",JSONObject.toJSONString(itemIds),typeName);
        OperateRecord operateRecord = new OperateRecord();
        operateRecord.setOperateType(itemIds.size()>1?37:36);
        operateRecord.setDetail("删除数据字典");
        operateRecord.setOperatorCode(ApplicationUtils.getWorkingUser().getUsername());
        operateRecord.setOperatorName(ApplicationUtils.getWorkingUser().getName());
        operateRecord.setSpId(ApplicationUtils.getWorkingSpId());
        operateRecord.setOperateResult(OPERATE_RESULT_SUCCESS);
        operateRecord.setMenu("dictionariesInfo");
        operateRecord.setCommonInfo(typeName);
        operateRecord.setDetail("删除数据字典【" + typeName + "】中的类型【" + operateRecordMapper.selectNameByItemId(itemIds) + "】");
        operateRecord.setCreatedAt(new Date());
        operateRecord.setUpdatedAt(new Date());
        operateRecordMapper.insert(operateRecord);
        dProvider.remove(RemoveDictionaryItemCommand.builder().itemIds(itemIds).build());
        if( "sync_alarm_to_sk".equals(code) ) {
            redisUtil.del(Constants.SYNC_ALAM_TO_SK_IMEIS_REDIS_KEY);
        }
    }

    @Override
    public void switchDictionary(String dictId, Integer state) {
        if (state > Constants.INT_ONE || state < Constants.INT_ZERO) {
            throw new GlobalAuthenticationException("参数不合法");
        }
        UpdateParamConfigCommand command = UpdateParamConfigCommand.builder().id(dictId)
                .updatedBy(getUserBackendId()).state(RunningState.parse(state)).build();
        if (!cProvider.update(command)) {
            throw new GlobalAuthenticationException("上下线操作失败");
        }
    }
}
